package com.utry.lib.annotation


import com.alibaba.fastjson.JSON
import com.alibaba.fastjson.JSONObject
import com.google.auto.service.AutoService
import com.utry.lib.annotation.data.ComponentData
import java.io.File
import java.io.FileOutputStream
import java.io.OutputStreamWriter
import javax.annotation.processing.*
import javax.lang.model.SourceVersion
import javax.lang.model.element.Element
import javax.lang.model.element.TypeElement
import javax.tools.Diagnostic
import javax.tools.StandardLocation

/**
 * @description: lab
 * @author: wangxf
 * @date: 2023/5/22 14:15
 */
@AutoService(Processor::class) // 告诉 annotationProcessor 在 project()（编译）应用时要自动执行该类
@SupportedSourceVersion(SourceVersion.RELEASE_8) // 声明我们所支持的jdk版本
@SupportedAnnotationTypes("com.utry.lib.annotation.ComponentSign")
// 声明该注解处理器想要处理那些注解
class GenerateClassProcessor : AbstractProcessor() {
    private val TAG = "GenerateClassProcessor"

    private lateinit var messager: Messager // 日志打印，在java环境下不能使用 android.util.log.e()
    private lateinit var filer: Filer //文件处理工具

    private val OutputFileName = "destination.ini" // 输出的文件名称
    override fun init(processingEnv: ProcessingEnvironment) {
        super.init(processingEnv)
        messager = processingEnv.messager
        filer = processingEnv.filer
        println("GenerateClassProcessor: init")
    }

    override fun process(
        annotations: MutableSet<out TypeElement>,
        roundEnv: RoundEnvironment
    ): Boolean {
        println("${TAG}:process   ${this.toString()}")
        /*
         * 通过处理器环境上下文 roundEnv 分别获取项目中标记的 ActivityDestination.class 和 FragmentDestination.class 注解。
         * 此目的就是为了收集项目中哪些类被注解标记了
         */
        val componentElements = roundEnv.getElementsAnnotatedWith(ComponentSign::class.java)

        if (componentElements.isNotEmpty()) {

            val destMap = HashMap<String, JSONObject>()
            var content = handleDestination(componentElements, ComponentSign::class.java, destMap)

            if (content == null) {
                return true;
            }
            val res =
                filer.createResource(StandardLocation.CLASS_OUTPUT, "", OutputFileName) // 创建源文件
            val resPath = res.toUri().path

            val appPath = resPath.substring(1, resPath.indexOf("lab") + 3)

            val assetsPath = "${appPath}/base/src/main/assets/"

            messager.printMessage(Diagnostic.Kind.NOTE, "\nresPath --> $assetsPath\n")

            // app/src/main/assets/ 目录如果不存在，就创建出来
            val file = File(assetsPath)
            if (!file.exists()) {
                file.mkdirs()
            }

            // 每次都覆盖 app/src/main/assets/{OutputFileName} 文件
            val outputFile = File(file, OutputFileName)
            var tag = outputFile.exists();
            if (!tag) {
                outputFile.createNewFile()
            }

            val fos = FileOutputStream(outputFile, tag)
            val writer = OutputStreamWriter(fos, "UTF-8")
            println("write：${content}")
            if (tag) {
                writer.write("\n")
            }
            writer.write(content.name)
            writer.write("=")
            writer.write(JSON.toJSONString(content))
            writer.flush()

            writer.close()
            fos.close()
        }
        return true
    }

    private fun handleDestination(
        elements: Set<Element>,
        annotationClz: Class<out Annotation>,
        destMap: HashMap<String, JSONObject>
    ): ComponentData? {
        if (elements.isEmpty()) {
            return null;
        }

        var data: ComponentData? = null;
        elements.forEach {
            data = ComponentData(it.simpleName.toString())
            println("simpleName:${it.simpleName}")
            val annotation = it.getAnnotation(annotationClz)
            if(annotation is ComponentSign){
                ComponentData.copyData(data!!,annotation)
            }

        }

        return data
    }

}